//////////////////////////////////////////////////////////////////////////////
//
// File Name:  conGuy.h
//
//
// Author:   GiTM.soccerist
// Date:    
// System:   Linux
// Compiler: 
//
//
// Description:  This class manages and processes all the necessary actions
//   required to connect to bnet.  (accnt, pwd and auth challenges).
//   It does NOT handle the parsing of the chat packets following the
//   connect completed.
//
// Status:  Near complete.
//

#ifndef CONGUY_H
#define CONGUY_H


#include<iostream>
#include<string>
#include<fstream>
#include<list>

using namespace std;

#include <qobject.h>
#include <q3socketdevice.h>
#include <qmutex.h>
#include <qdatetime.h>
#include <qthread.h>
#include <q3dns.h>

#include "src/conGuy/buff.h"
#include "src/conGuy/types.h"
#include "src/authGuy/authGuy.h"
#include "src/event/BnetEvent.h"
#include "src/gui/SettingsDialog.h"
#include "src/gui/ChatDialog.h"

class conGuy;

// sendQueue class:
//    This class contains a list of strings that need to be sent out 
//    to the server.
class sendQueue {
 public:
  list<string> out;
  QMutex mutex;
};

class SleeperThread : public QThread
{
 public:
    static void sleep(unsigned long secs)
        {
            QThread::sleep(secs);
        }    
    static void msleep(unsigned long msecs)
        {
            QThread::msleep(msecs);
        }
};

// conGuy class:
// Inherit QThread so that I may use the sleep and usleep functions.
class conGuy : public QObject {
  Q_OBJECT


 public:
  conGuy(ChatDialog *chatDialog);
  ~conGuy();  // Close socket if it's open.

  // bool variable to tell the while loop in bot.cc's thread is done.
  bool done;

  bool connectNow();
  bool disconnectNow();

  bool isConnected();
  sendQueue* getSendQueue();

  BnetEvent gimmeEvent();    // Returns an event object.
  bool say(string msg);

  // Unused for now:
  int getSd();  // Returns the socket descriptor for use elsewhere.
  string homeChannel();  // Returns the desired homeChannel.
  string username();
  bool getHaveOps();
  bool setHaveOps(bool ops);

  //   virtual void run();  // Thread that opens the SettingsDialog.
 signals:
  void appendChat(QString, QString);
  void connectedToBnet();
protected slots:
  bool connectToBnet();

 private:
  void run(); // Empty function, Not used.  
 void log(string msg);
 void debuglog(string msg);
 ChatDialog *chatDialog_; // Only used to emit logging to.
  SettingsDialog *settingsDialog;

  bool sendBuffOut();  // Send sendBuff out.
  bool read_config();

    //  bool my_poll_in(int timeout);
  string printErrorType( Q3SocketDevice::Error err );
    
  bool readFullPacket( const int& timeout = -1 );

  int readit(void*msg_data, unsigned int msg_len);
  bool writeit(void*msg_data, unsigned int msg_len);

  u32 getExeVer();
  u32 getVersionByte();

  // Buffers
  buff sendBuff;
  buff recvBuff;

  // Queue of string that need to be sent out to the server.
  sendQueue toSend;

  // Flood protection stuff
  QDateTime lastSendTime;
  u16 lastSendSize;

  // These are adjustable parameters used in our flood control.
  long sleep_sec_req;  // Minimum required seconds to sleep
  long sleep_msec_req; // Minimum required microseconds to sleep.
  long sleep_msec_per_byte;  // Number of microseconds to sleep per byte
                             // when packet size is > 30 bytes.

  void enableFloodControl( const bool& enable = true );
  bool updateLastSendTime();
  bool sleepRequiredTime();  // Call this before every send.
                             // It does a sleep() or usleep() as required.
  
  
  // Variables read in from the config file and used in the connect.
/*   string bot_gateway;    // This is the gateway the actual bot will run on. */
/*   string gateway;        // The gateway this conGuy is working for. */
  Q3Dns *dns;
  string server;     // Server address to connect to.
  int port;
  string home_channel;
  string account;
  string password;
  string unique_username;
  string hash1;
  string hash2;
  string hash3;
  string cdkey;
  string starcraftVersion_;  // We use this to determine the
                             // versionByte and the exeVer.

  bool haveOps;  // This is set in bot.cc in switch case EID_USERFLAGS.

  int sd;  // Socket Descriptor.  (Important number ;))
  Q3SocketDevice* qtsocket;
  
  // Authorization Object.  He holds auth functions and vars.
  authGuy auth;

  bool handle_nonchat();     // Handle a pkt that's not SID_CHATEVENT
  bool trash_curr_packet();  // Throw away the current packet.


  // Here are the packet handling functions:
  // (s stands for send, r stands for recv, pkt stands for packet)
  // I have found it annoying enough at work looking at undocumented code that
  // shall never adhere to that low standard.

  // Recieive functions have a precondition of the recvBuff being already 
  //   stripped.
  bool s_pkt_protocol();
  bool s_pkt_SID_AUTH_INFO();
  bool s_pkt_SID_PING(u32 pingValue);
  bool s_pkt_SID_AUTH_CHECK();
  bool s_pkt_SID_LOGONRESPONSE();
  bool s_pkt_SID_UDPPINGRESPONSE();
  bool s_pkt_SID_ENTERCHAT();
  bool s_pkt_SID_GETCHANNELLIST();
  bool s_pkt_SID_CHATCOMMAND(string msg);
  bool s_pkt_SID_JOINCHANNEL(string channel);
  bool s_pkt_SID_LEAVECHAT();
  bool s_pkt_SID_NULL();


  bool r_pkt_SID_PING(u32 &pingValue);
  bool r_pkt_SID_AUTH_INFO();
  bool r_pkt_SID_AUTH_CHECK();
  bool r_pkt_SID_LOGONRESPONSE();
  bool r_pkt_SID_GETCHANNELLIST();
  bool r_pkt_SID_ENTERCHAT();
  bool r_pkt_SID_FLOODDETECTED();
  bool r_pkt_SID_MESSAGEBOX();
};





// Below are the battle.net packet ID's.
#define SID_NULL			0x00  
#define SID_CLIENTID			0x05  
#define SID_STARTVERSIONING		0x06  
#define SID_REPORTVERSION		0x07  
#define SID_GETADVLISTEX		0x09  
#define SID_ENTERCHAT			0x0A  
#define SID_GETCHANNELLIST		0x0B  
#define SID_JOINCHANNEL			0x0C  
#define SID_CHATCOMMAND			0x0E  
#define SID_CHATEVENT			0x0F  
#define SID_LEAVECHAT                   0x10
#define SID_FLOODDETECTED		0x13  
#define SID_UDPPINGRESPONSE		0x14  
#define SID_MESSAGEBOX			0x19  
#define SID_PING			0x25  
#define SID_READUSERDATA		0x26  
#define SID_WRITEUSERDATA		0x27  
#define SID_LOGONCHALLENGE		0x28  
#define SID_LOGONRESPONSE		0x29  
#define SID_CREATEACCOUNT		0x2A  
#define SID_CHANGEPASSWORD		0x31  
#define SID_LOGONRESPONSE2		0x3A  
#define SID_CREATEACCOUNT2		0x3D  
#define SID_LOGONREALMEX		0x3E
#define SID_AUTH_INFO			0x50  
#define SID_AUTH_CHECK			0x51  
#define SID_FRIENDLIST			0x65  
#define SID_FRIENDUPDATE		0x66  
#define SID_FRIENDADDED			0x67  
#define SID_FRIENDREMOVED		0x68  
#define SID_FRIENDMOVED			0x69  
#define SID_FINDCLANCANDIDATES		0x70  
#define SID_INVITEMULTIPLEUSERS		0x71  
#define SID_DISBANDCLAN			0x73  
#define SID_CLANINFO			0x75  
#define SID_CLANREQUEST			0x77  
#define SID_CLANINVITE			0x79  
#define SID_CLANMOTD			0x7C  
#define SID_CLANMEMBERLIST		0x7D  
#define SID_CLANMEMBERUPDATE		0x7F  


// Below are the Battle.net/Starcraft UDP packet ID's.
#define PKT_SERVERPING			0x05  
#define PKT_KEEPALIVE			0x07  
#define PKT_CONNTEST2			0x09  


#define BROOD_WAR_PRODUCT_ID            0x53455850

#endif
